#include "qlib/geo/ruler.h"
#include "qlib/utils/font.h"

#include <iomanip>
#include <string>

namespace qlib {

Ruler::Ruler() {
  start = {0, 0};
  end = {0, 0};

  box.resize(2);
};

Ruler::Ruler(Vec2d _start, Vec2d _end) {
  start = _start;
  end = _end;
}

Ruler::Ruler(const Ruler& other) {
  operator=(other);
}

Ruler& Ruler::operator=(const Ruler& other) {
  step = other.step;
  hLength = other.hLength;
  center = other.center;
  start = other.start;
  end = other.end;
  length = other.length;
  layer = other.layer;
  datatype = other.datatype;
  box = other.box;
  repetition = other.repetition;

  properties.resize(other.properties.size());
  for (size_t i = 0; i < properties.size(); i++) {
    properties[i] = Property::create();
    if (other.properties[i]) {
      properties[i] = Property::create();
      *properties[i] = *other.properties[i];
    }
  }

  lines = other.lines;

  return *this;
}

Ruler::s_ptr Ruler::copy() const {
  auto res = Ruler::create();
  *res = *this;

  return res;
}
void Ruler::rotate(double angle, Vec2d center) {
  double ca = cos(angle);
  double sa = sin(angle);

  Vec2d vt;

  {
    vt = start - center;
    start.x = vt.x * ca - vt.y * sa + center.x;
    start.y = vt.x * sa + vt.y * ca + center.y;
  }

  {
    vt = end - center;
    end.x = vt.x * ca - vt.y * sa + center.x;
    end.y = vt.x * sa + vt.y * ca + center.y;
  }
}
void Ruler::translate(double dx, double dy) {
  start += {dx, dy};
  end += {dx, dy};
}

Vec2dArray Ruler::render_aabb() {
  return bounding_box();
}

Polygon::s_ptr Ruler::to_polygon() {
  Polygon::s_ptr polygon = Polygon::create();

  Vec2dArray& res = polygon->points;
  res.push_back(start);
  res.push_back(end);

  Vec2d vec = (end - start) / step;
  Vec2d vec_h = qlib::Vec2d(-vec.y, vec.x);
  if (vec_h.y < 0) {
    vec_h *= -1;
  }

  Vec2d p;
  for (size_t i = 0; i < step; i++) {
    p = start + vec * i;
    res.push_back(p);

    p = p + vec_h * hLength;
    res.push_back(p);
  }

  for (auto& p : res) {
    box_and_point(box, p);
  }

  return polygon;
}

Vec2dArray Ruler::render_poly() {
  return to_polygon()->points;
}

Vec2dArray Ruler::render_absorp() {
  return to_polygon()->points;
}

Vec2dArray Ruler::bounding_box() {
  Vec2dArray res(2);
  auto& min = res[0];
  auto& max = res[1];
  min.x = min.y = DBL_MAX;
  max.x = max.y = -DBL_MAX;
  auto points = Vec2dArray{start, end};
  for (auto& p : points) {
    if (p.x < min.x)
      min.x = p.x;
    if (p.x > max.x)
      max.x = p.x;
    if (p.y < min.y)
      min.y = p.y;
    if (p.y > max.y)
      max.y = p.y;
  }
  return res;
}

void Ruler::mirror(Vec2d p0, Vec2d p1) {
  Vec2d v = p1 - p0;
  double tmp = v.length_sq();
  if (tmp == 0)
    return;

  Vec2d r = v * (2 / tmp);
  Vec2d p2 = p0 * 2;

  start = v * (start - p0).inner(r) - start + p2;
  end = v * (end - p0).inner(r) - end + p2;
}

double angle_direction(Vec2d p1, Vec2d p2) {
  double dx = p2.x - p1.x;
  double dy = p2.y - p1.y;
  if (abs(dy) < 0.0001) {
    if (dx > 0)
      return 0;
    if (dx < 0)
      return M_PI;
  }
  if (abs(dx) < 0.0001) {
    if (dy > 0)
      return M_PI / 2;
    if (dy < 0)
      return (M_PI * 3) / 2;
  }
  double angle = atan(abs(dy / dx));
  if (dy > 0) {
    if (dx > 0)
      // 第一象限
      return angle;
    if (dx < 0)
      // 第二象限
      return M_PI - angle;
  }
  if (dy < 0) {
    if (dx < 0)
      // 第三象限
      return M_PI + angle;
    if (dx > 0)
      // 第四象限
      return 2 * M_PI - angle;
  }
  return 0;
};

/**
   * @brief 按点位和方向生成一定长度的线段
   * 
   * @param[in] pos 点
   * @param[in] direct 方向角度, 弧度
   * @param[in] length 长度
   * @return[out] Vec2dArray 线段
   * 
   */
Vec2dArray point_to_line(const qlib::Vec2d& pos, double direct, double length) {
  std::vector<qlib::Vec2d> line;
  double dx = length * cos(direct);
  double dy = length * sin(direct);
  line.push_back(pos);
  line.push_back(qlib::Vec2d(pos.x + dx, pos.y + dy));
  return line;
};

Vec2dArray Ruler::get_scale_lines() {
  auto p1 = start;
  auto p2 = end;
  // 绘制区域
  auto box_x_min = 0;
  auto box_y_min = 100;
  auto box_x_max = 0;
  auto box_y_max = 100;

  // // 步长
  // double step = 10;
  double angle = angle_direction(p1, p2);
  double cal_angle = 0;
  double quadrant = 1;
  Vec2d start_pos, end_pos;
  // 1象限
  if (angle >= 0 && angle <= M_PI / 2) {
    cal_angle = angle + M_PI / 2;
    quadrant = angle == 0 ? 4 : 1;
  }
  // 2象限
  if (angle > M_PI / 2 && angle <= M_PI) {
    cal_angle = angle - M_PI / 2;
    quadrant = 2;
  }
  // 3象限
  if (angle > M_PI && angle <= (M_PI * 3) / 2) {
    cal_angle = angle - M_PI / 2;
    quadrant = 3;
  }
  // 4象限
  if (angle > (M_PI * 3) / 2 && angle <= M_PI * 2) {
    cal_angle = angle + M_PI / 2;
    quadrant = 4;
  }
  double dx = p2.x - p1.x;
  double dy = p2.y - p1.y;
  double len = sqrt(dx * dx + dy * dy);
  double n = floor(len / step);
  n = n < 1 ? 1 : n;
  double x_step = dx / n;
  double y_step = dy / n;

  std::vector<qlib::Vec2d> lines;
  std::vector<qlib::Vec2d> line;
  // 绘制起点->终点
  lines.push_back(p1);
  lines.push_back(p2);
  // 起点刻度
  line = point_to_line(p1, cal_angle, 15);
  lines.push_back(line[0]);
  lines.push_back(line[1]);

  // // 绘制中间视图区域内刻度
  // bool find_left = false;
  // int txt = 0;
  // for (int i = 0; i < n; i++) {
  //   // 绘制刻度线和刻度值
  //   qlib::Vec2d p{p1.x + i * x_step, p1.y + i * y_step};
  //   if (i % 5 == 0) {
  //     line = point_to_line(p, cal_angle, 15);
  //     txt = i * step;
  //   } else {
  //     line = point_to_line(p, cal_angle, 5);
  //   }
  //   lines.push_back(line[0]);
  //   lines.push_back(line[1]);
  //   if (i == 0) {
  //     start_pos = line[1];
  //   }
  // }
  // 终点刻度
  line = point_to_line(p2, cal_angle, 15);
  lines.push_back(line[0]);
  lines.push_back(line[1]);

  end_pos = line[1];
  return lines;
};

Vec2dArray Ruler::get_label_lines() {
  double d = start.distance(end);
  auto start_text = get_text("0", start, 30, 0, qlib::Anchor::SW);
  auto end_text = get_text(format_digits(d, 6), end, 30, 0, qlib::Anchor::SW);
  start_text.insert(start_text.end(), end_text.begin(), end_text.end());
  return start_text;
}

Vec2dArray Ruler::get_lines(const Vec2d& p1, const Vec2d& p2, double step, double unit_scale) {
  // 绘制区域
  auto box_x_min = 0;
  auto box_y_min = 100;
  auto box_x_max = 0;
  auto box_y_max = 100;

  // // 步长
  // double step = 10;
  double angle = angle_direction(p1, p2);
  double cal_angle = 0;
  double quadrant = 1;
  Anchor ahr = Anchor::O;
  Vec2d start_pos, end_pos;
  // 1象限
  if (angle >= 0 && angle <= M_PI / 2) {
    cal_angle = angle + M_PI / 2;
    quadrant = angle == 0 ? 4 : 1;
  }
  // 2象限
  if (angle > M_PI / 2 && angle <= M_PI) {
    cal_angle = angle - M_PI / 2;
    quadrant = 2;
  }
  // 3象限
  if (angle > M_PI && angle <= (M_PI * 3) / 2) {
    cal_angle = angle - M_PI / 2;
    quadrant = 3;
  }
  // 4象限
  if (angle > (M_PI * 3) / 2 && angle <= M_PI * 2) {
    cal_angle = angle + M_PI / 2;
    quadrant = 4;
  }
  double dx = p2.x - p1.x;
  double dy = p2.y - p1.y;
  double len = sqrt(dx * dx + dy * dy);
  double n = floor(len / step);
  n = n < 1 ? 1 : n;
  double x_step = dx / n;
  double y_step = dy / n;

  std::vector<qlib::Vec2d> lines;
  std::vector<qlib::Vec2d> line;

  // 绘制起点->终点
  lines.push_back(p1);
  lines.push_back(p2);

  // 起点刻度
  line = point_to_line(p1, cal_angle, 15);
  lines.push_back(line[0]);
  lines.push_back(line[1]);

  // // 绘制中间视图区域内刻度
  // bool find_left = false;
  // int txt = 0;
  // for (int i = 0; i < n; i++) {
  //   // 绘制刻度线和刻度值
  //   qlib::Vec2d p{p1.x + i * x_step, p1.y + i * y_step};
  //   if (i % 5 == 0) {
  //     line = point_to_line(p, cal_angle, 15);
  //     txt = i * step;
  //   } else {
  //     line = point_to_line(p, cal_angle, 5);
  //   }
  //   lines.push_back(line[0]);
  //   lines.push_back(line[1]);
  //   if (i == 0) {
  //     start_pos = line[1];
  //   }
  // }
  // 终点刻度
  line = point_to_line(p2, cal_angle, 15);
  lines.push_back(line[0]);
  lines.push_back(line[1]);

  // 文本线条
  double d = start.distance(end);
  auto start_text = get_text("0", p1, 30, 0, qlib::Anchor::SW);
  auto end_text = get_text(format_digits(d, 6), p2, 30, 0, qlib::Anchor::SW);

  lines.insert(lines.end(), start_text.begin(), start_text.end());
  lines.insert(lines.end(), end_text.begin(), end_text.end());
  return lines;
}

// double Ruler::getRotation(){}

void Ruler::setRotation(double rotation) {}

}  // namespace qlib